Package org.python.pydev.editor.codecompletion

Source Code of org.python.pydev.editor.codecompletion.PyCodeCompletion

/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Aug 11, 2004
*
* @author Fabio Zadrozny
*/
package org.python.pydev.editor.codecompletion;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.swt.graphics.Image;
import org.python.pydev.core.ExtensionHelper;
import org.python.pydev.core.FullRepIterable;
import org.python.pydev.core.ICodeCompletionASTManager;
import org.python.pydev.core.ICodeCompletionASTManager.ImportInfo;
import org.python.pydev.core.ICompletionState;
import org.python.pydev.core.IDefinition;
import org.python.pydev.core.ILocalScope;
import org.python.pydev.core.IModule;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.IToken;
import org.python.pydev.core.ImmutableTuple;
import org.python.pydev.core.MisconfigurationException;
import org.python.pydev.core.OrderedMap;
import org.python.pydev.core.PythonNatureWithoutProjectException;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.core.docutils.PySelection.LineStartingScope;
import org.python.pydev.core.log.Log;
import org.python.pydev.core.structure.CompletionRecursionException;
import org.python.pydev.core.structure.FastStack;
import org.python.pydev.editor.codecompletion.revisited.AbstractASTManager;
import org.python.pydev.editor.codecompletion.revisited.AssignAnalysis;
import org.python.pydev.editor.codecompletion.revisited.CompletionCache;
import org.python.pydev.editor.codecompletion.revisited.CompletionState;
import org.python.pydev.editor.codecompletion.revisited.modules.CompiledModule;
import org.python.pydev.editor.codecompletion.revisited.modules.SourceModule;
import org.python.pydev.editor.codecompletion.revisited.modules.SourceToken;
import org.python.pydev.editor.codecompletion.revisited.visitors.Definition;
import org.python.pydev.editor.codecompletion.revisited.visitors.FindScopeVisitor;
import org.python.pydev.editor.codecompletion.shell.AbstractShell;
import org.python.pydev.editor.refactoring.PyRefactoringFindDefinition;
import org.python.pydev.editor.refactoring.RefactoringRequest;
import org.python.pydev.logging.DebugSettings;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.ClassDef;
import org.python.pydev.parser.jython.ast.FunctionDef;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.NameTok;
import org.python.pydev.parser.jython.ast.Return;
import org.python.pydev.parser.jython.ast.stmtType;
import org.python.pydev.parser.jython.ast.factory.AdapterPrefs;
import org.python.pydev.parser.jython.ast.factory.PyAstFactory;
import org.python.pydev.parser.visitors.NodeUtils;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.ui.UIConstants;

import com.aptana.shared_core.callbacks.ICallback;
import com.aptana.shared_core.structure.Tuple;

/**
* @author Dmoore
* @author Fabio Zadrozny
*/
public class PyCodeCompletion extends AbstractPyCodeCompletion {

    /**
     * Called when a recursion exception is detected.
     */
    public static ICallback<Object, CompletionRecursionException> onCompletionRecursionException;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public List getCodeCompletionProposals(ITextViewer viewer, CompletionRequest request) throws CoreException,
            BadLocationException, IOException, MisconfigurationException, PythonNatureWithoutProjectException {
        if (request.getPySelection().getCursorLineContents().trim().startsWith("#")) {
            //this may happen if the context is still not correctly computed in python
            return new PyStringCodeCompletion().getCodeCompletionProposals(viewer, request);
        }
        if (DebugSettings.DEBUG_CODE_COMPLETION) {
            Log.toLogFile(this, "Starting getCodeCompletionProposals");
            Log.addLogLevel();
            Log.toLogFile(this, "Request:" + request);
        }

        ArrayList<ICompletionProposal> ret = new ArrayList<ICompletionProposal>();

        //let's see if we should do a code-completion in the current scope...

        //this engine does not work 'correctly' in the default scope on:
        //- class definitions - after 'class' and before '('
        //- method definitions - after 'def' and before '('
        PySelection ps = request.getPySelection();
        int lineCtx = ps.isInDeclarationLine();
        if (lineCtx != PySelection.DECLARATION_NONE) {
            if (lineCtx == PySelection.DECLARATION_METHOD) {
                Image imageOverride = PydevPlugin.getImageCache().get(UIConstants.METHOD_ICON);
                String lineContentsToCursor = ps.getLineContentsToCursor();
                LineStartingScope scopeStart = ps.getPreviousLineThatStartsScope(PySelection.CLASS_TOKEN, false,
                        PySelection.getFirstCharPosition(lineContentsToCursor));

                String className = null;
                if (scopeStart != null) {
                    className = PySelection.getClassNameInLine(scopeStart.lineStartingScope);
                    if (className != null && className.length() > 0) {
                        Tuple<List<String>, Integer> insideParensBaseClasses = ps.getInsideParentesisToks(true,
                                scopeStart.iLineStartingScope);
                        if (insideParensBaseClasses != null) {

                            //representation -> token and base class
                            OrderedMap<String, ImmutableTuple<IToken, String>> map = new OrderedMap<String, ImmutableTuple<IToken, String>>();

                            for (String baseClass : insideParensBaseClasses.o1) {
                                try {
                                    ICompletionState state = new CompletionState(-1, -1, null, request.nature,
                                            baseClass);
                                    state.setActivationToken(baseClass);
                                    state.setIsInCalltip(false);

                                    IPythonNature pythonNature = request.nature;
                                    checkPythonNature(pythonNature);

                                    ICodeCompletionASTManager astManager = pythonNature.getAstManager();
                                    if (astManager == null) {
                                        //we're probably still loading it.
                                        return ret;
                                    }
                                    //Ok, looking for a token in globals.
                                    IModule module = request.getModule();
                                    if (module == null) {
                                        continue;
                                    }
                                    IToken[] comps = astManager.getCompletionsForModule(module, state, true, true);
                                    for (int i = 0; i < comps.length; i++) {
                                        IToken iToken = comps[i];
                                        String representation = iToken.getRepresentation();
                                        ImmutableTuple<IToken, String> curr = map.get(representation);
                                        if (curr != null && curr.o1 instanceof SourceToken) {
                                            continue; //source tokens are never reset!
                                        }

                                        int type = iToken.getType();
                                        if (iToken instanceof SourceToken
                                                && ((SourceToken) iToken).getAst() instanceof FunctionDef) {
                                            map.put(representation, new ImmutableTuple<IToken, String>(iToken,
                                                    baseClass));

                                        } else if (type == IToken.TYPE_FUNCTION || type == IToken.TYPE_UNKNOWN
                                                || type == IToken.TYPE_BUILTIN) {
                                            map.put(representation, new ImmutableTuple<IToken, String>(iToken,
                                                    baseClass));

                                        }
                                    }
                                } catch (Exception e) {
                                    Log.log(e);
                                }
                            }

                            for (ImmutableTuple<IToken, String> tokenAndBaseClass : map.values()) {
                                FunctionDef functionDef = null;

                                //No checkings needed for type (we already did that above).
                                if (tokenAndBaseClass.o1 instanceof SourceToken) {
                                    SourceToken sourceToken = (SourceToken) tokenAndBaseClass.o1;
                                    SimpleNode ast = sourceToken.getAst();
                                    if (ast instanceof FunctionDef) {
                                        functionDef = (FunctionDef) ast;
                                    } else {
                                        functionDef = sourceToken.getAliased().createCopy();
                                        NameTok t = (NameTok) functionDef.name;
                                        t.id = sourceToken.getRepresentation();
                                    }
                                } else {
                                    //unfortunately, for builtins we usually cannot trust the parameters.
                                    String representation = tokenAndBaseClass.o1.getRepresentation();
                                    PyAstFactory factory = new PyAstFactory(new AdapterPrefs(ps.getEndLineDelim(),
                                            request.nature));
                                    functionDef = factory.createFunctionDef(representation);
                                    functionDef.args = factory.createArguments(true);
                                    functionDef.args.vararg = new NameTok("args", NameTok.VarArg);
                                    functionDef.args.kwarg = new NameTok("kwargs", NameTok.KwArg);
                                    if (!representation.equals("__init__")) {
                                        functionDef.body = new stmtType[] { new Return(null) }; //signal that the return should be added
                                    }
                                }

                                if (functionDef != null) {
                                    ret.add(new OverrideMethodCompletionProposal(ps.getAbsoluteCursorOffset(), 0, 0,
                                            imageOverride, functionDef, tokenAndBaseClass.o2, //baseClass
                                            className));
                                }
                            }

                        }
                    }
                }
            }
            request.showTemplates = false;
            return ret;
        }

        try {
            IPythonNature pythonNature = request.nature;
            checkPythonNature(pythonNature);

            ICodeCompletionASTManager astManager = pythonNature.getAstManager();
            if (astManager == null) {
                //we're probably still loading it.
                return ret;
            }

            //list of Object[], IToken or ICompletionProposal
            List<Object> tokensList = new ArrayList<Object>();
            lazyStartShell(request);
            String trimmed = request.activationToken.replace('.', ' ').trim();

            ImportInfo importsTipper = getImportsTipperStr(request);

            int line = request.doc.getLineOfOffset(request.documentOffset);
            IRegion region = request.doc.getLineInformation(line);

            ICompletionState state = new CompletionState(line, request.documentOffset - region.getOffset(), null,
                    request.nature, request.qualifier);
            state.setIsInCalltip(request.isInCalltip);

            Map<String, IToken> alreadyChecked = new HashMap<String, IToken>();

            boolean importsTip = false;

            if (importsTipper.importsTipperStr.length() != 0) {
                //code completion in imports
                request.isInCalltip = false; //if found after (, but in an import, it is not a calltip!
                request.isInMethodKeywordParam = false; //if found after (, but in an import, it is not a calltip!
                importsTip = doImportCompletion(request, astManager, tokensList, importsTipper);

            } else if (trimmed.length() > 0 && request.activationToken.indexOf('.') != -1) {
                //code completion for a token
                doTokenCompletion(request, astManager, tokensList, trimmed, state);
                handleKeywordParam(request, line, alreadyChecked);

            } else {
                //go to globals
                doGlobalsCompletion(request, astManager, tokensList, state);

                //At this point, after doing the globals completion, we may also need to check if we need to show
                //keyword parameters to the user.
                handleKeywordParam(request, line, alreadyChecked);
            }

            String lowerCaseQual = request.qualifier.toLowerCase();
            if (lowerCaseQual.length() >= PyCodeCompletionPreferencesPage.getArgumentsDeepAnalysisNChars()) {
                //this can take some time on the analysis, so, let's let the user choose on how many chars does he
                //want to do the analysis...
                state.pushFindResolveImportMemoryCtx();
                try {
                    for (Iterator<Object> it = tokensList.listIterator(); it.hasNext();) {
                        Object o = it.next();
                        if (o instanceof IToken) {
                            it.remove(); // always remove the tokens from the list (they'll be re-added later once they are filtered)

                            IToken initialToken = (IToken) o;

                            IToken token = initialToken;
                            String strRep = token.getRepresentation();
                            IToken prev = alreadyChecked.get(strRep);

                            if (prev != null) {
                                if (prev.getArgs().length() != 0) {
                                    continue; // we already have a version with args... just keep going
                                }
                            }

                            if (!strRep.toLowerCase().startsWith(lowerCaseQual)) {
                                //just re-add it if we're going to actually use it (depending on the qualifier)
                                continue;
                            }

                            IModule current = request.getModule();

                            while (token.isImportFrom()) {
                                //we'll only add it here if it is an import from (so, set the flag to false for the outer add)

                                if (token.getArgs().length() > 0) {
                                    //if we already have the args, there's also no reason to do it (that's what we'll do here)
                                    break;
                                }
                                ICompletionState s = state.getCopyForResolveImportWithActTok(token.getRepresentation());
                                s.checkFindResolveImportMemory(token);

                                ImmutableTuple<IModule, IToken> modTok = astManager.resolveImport(s, token, current);
                                IToken token2 = modTok.o2;
                                current = modTok.o1;
                                if (token2 != null && initialToken != token2) {
                                    String args = token2.getArgs();
                                    if (args.length() > 0) {
                                        //put it into the map (may override previous if it didn't have args)
                                        initialToken.setArgs(args);
                                        initialToken.setDocStr(token2.getDocStr());
                                        if (initialToken instanceof SourceToken && token2 instanceof SourceToken) {
                                            SourceToken initialSourceToken = (SourceToken) initialToken;
                                            SourceToken token2SourceToken = (SourceToken) token2;
                                            initialSourceToken.setAst(token2SourceToken.getAst());
                                        }
                                        break;
                                    }
                                    if (token2 == null
                                            || (token2.equals(token) && token2.getArgs().equals(token.getArgs()) && token2
                                                    .getParentPackage().equals(token.getParentPackage()))) {
                                        break;
                                    }
                                    token = token2;
                                } else {
                                    break;
                                }
                            }

                            alreadyChecked.put(strRep, initialToken);
                        }
                    }

                } finally {
                    state.popFindResolveImportMemoryCtx();
                }
            }

            tokensList.addAll(alreadyChecked.values());
            changeItokenToCompletionPropostal(viewer, request, ret, tokensList, importsTip, state);
        } catch (CompletionRecursionException e) {
            if (onCompletionRecursionException != null) {
                onCompletionRecursionException.call(e);
            }
            if (DebugSettings.DEBUG_CODE_COMPLETION) {
                Log.toLogFile(e);
            }
            //PydevPlugin.log(e);
            //ret.add(new CompletionProposal("",request.documentOffset,0,0,null,e.getMessage(), null,null));
        }

        if (DebugSettings.DEBUG_CODE_COMPLETION) {
            Log.remLogLevel();
            Log.toLogFile(this, "Finished completion. Returned:" + ret.size() + " completions.\r\n");
        }

        return ret;
    }

    private void handleKeywordParam(CompletionRequest request, int line, Map<String, IToken> alreadyChecked)
            throws BadLocationException, CompletionRecursionException {
        if (request.isInMethodKeywordParam) {

            PySelection ps = new PySelection(request.doc, request.offsetForKeywordParam);
            RefactoringRequest findRequest = new RefactoringRequest(request.editorFile, ps, new NullProgressMonitor(),
                    request.nature, null);
            ArrayList<IDefinition> selected = new ArrayList<IDefinition>();
            PyRefactoringFindDefinition.findActualDefinition(findRequest, new CompletionCache(), selected);

            //Changed: showing duplicated parameters (only removing self and cls).
            //Tuple<List<String>, Integer> insideParentesisToks = ps.getInsideParentesisToks(false, completionRequestForKeywordParam.documentOffset);
            HashSet<String> ignore = new HashSet<String>();
            ignore.add("self");
            ignore.add("cls");
            //if(insideParentesisToks!=null && insideParentesisToks.o1 != null){
            //    for (String object : insideParentesisToks.o1) {
            //        ignore.add(object);
            //    }
            //}

            for (IDefinition iDefinition : selected) {
                if (iDefinition instanceof Definition) {
                    Definition definition = (Definition) iDefinition;
                    if (definition.ast != null) {
                        String args = NodeUtils.getNodeArgs(definition.ast);
                        String fullArgs = NodeUtils.getFullArgs(definition.ast);
                        StringTokenizer tokenizer = new StringTokenizer(args, "(, )");
                        while (tokenizer.hasMoreTokens()) {
                            String nextToken = tokenizer.nextToken();
                            if (ignore.contains(nextToken)) {
                                continue;
                            }
                            String kwParam = nextToken + "=";
                            SimpleNode node = new NameTok(kwParam, NameTok.KwArg);
                            SourceToken sourceToken = new SourceToken(node, kwParam, "", "", "", IToken.TYPE_LOCAL);
                            sourceToken.setDocStr(fullArgs);
                            alreadyChecked.put(kwParam, sourceToken);
                        }
                    }
                }
            }
        }
    }

    /**
     * Does a code-completion that will retrieve the globals in the module
     * @throws MisconfigurationException
     */
    private void doGlobalsCompletion(CompletionRequest request, ICodeCompletionASTManager astManager,
            List<Object> tokensList, ICompletionState state) throws CompletionRecursionException,
            MisconfigurationException {
        state.setActivationToken(request.activationToken);
        if (DebugSettings.DEBUG_CODE_COMPLETION) {
            Log.toLogFile(this, "astManager.getCompletionsForToken");
            Log.addLogLevel();
        }

        IModule module = request.getModule();
        if (module == null) {
            Log.remLogLevel();
            Log.toLogFile(this, "END astManager.getCompletionsForToken: null module");
            return;
        }
        IToken[] comps = astManager.getCompletionsForModule(module, state, true, true);
        if (DebugSettings.DEBUG_CODE_COMPLETION) {
            Log.remLogLevel();
            Log.toLogFile(this, "END astManager.getCompletionsForToken");
        }

        for (int i = 0; i < comps.length; i++) {
            tokensList.add(comps[i]);
        }
        tokensList.addAll(getGlobalsFromParticipants(request, state));
    }

    /**
     * Does a code-completion that will retrieve the all matches for some token in the module
     * @throws MisconfigurationException
     */
    private void doTokenCompletion(CompletionRequest request, ICodeCompletionASTManager astManager,
            List<Object> tokensList, String trimmed, ICompletionState state) throws CompletionRecursionException,
            MisconfigurationException {
        if (request.activationToken.endsWith(".")) {
            request.activationToken = request.activationToken.substring(0, request.activationToken.length() - 1);
        }

        final String initialActivationToken = request.activationToken;
        int parI = request.activationToken.indexOf('(');
        if (parI != -1) {
            request.activationToken = request.activationToken.substring(0, parI);
        }

        char[] toks = new char[] { '.', ' ' };

        boolean lookInGlobals = true;

        if (trimmed.equals("self") || FullRepIterable.getFirstPart(trimmed, toks).equals("self")) {
            lookInGlobals = !getSelfOrClsCompletions(request, tokensList, state, false, true, "self");

        } else if (trimmed.equals("cls") || FullRepIterable.getFirstPart(trimmed, toks).equals("cls")) {
            lookInGlobals = !getSelfOrClsCompletions(request, tokensList, state, false, true, "cls");

        }

        if (lookInGlobals) {
            state.setActivationToken(initialActivationToken);

            //Ok, looking for a token in globals.
            IModule module = request.getModule();
            if (module != null) {
                IToken[] comps = astManager.getCompletionsForModule(module, state, true, true);
                for (int i = 0; i < comps.length; i++) {
                    tokensList.add(comps[i]);
                }
            }
        }
    }

    /**
     * Does a code-completion that will check for imports
     * @throws MisconfigurationException
     */
    private boolean doImportCompletion(CompletionRequest request, ICodeCompletionASTManager astManager,
            List<Object> tokensList, ImportInfo importsTipper) throws CompletionRecursionException,
            MisconfigurationException {
        boolean importsTip;
        //get the project and make the code completion!!
        //so, we want to do a code completion for imports...
        //let's see what we have...

        importsTip = true;
        importsTipper.importsTipperStr = importsTipper.importsTipperStr.trim();
        IToken[] imports = astManager.getCompletionsForImport(importsTipper, request, false);
        for (int i = 0; i < imports.length; i++) {
            tokensList.add(imports[i]);
        }
        return importsTip;
    }

    /**
     * Checks if the python nature is valid
     */
    private void checkPythonNature(IPythonNature pythonNature) {
        if (pythonNature == null) {
            throw new RuntimeException("Unable to get python nature.");
        }
    }

    /**
     * Pre-initializes the shell (NOT in a thread, as we may need it shortly, so, no use in putting it into a thread)
     * @throws MisconfigurationException
     * @throws CoreException
     * @throws IOException
     * @throws PythonNatureWithoutProjectException
     */
    private void lazyStartShell(CompletionRequest request) throws IOException, CoreException,
            MisconfigurationException, PythonNatureWithoutProjectException {
        try {
            if (DebugSettings.DEBUG_CODE_COMPLETION) {
                Log.toLogFile(this, "AbstractShell.getServerShell");
            }
            if (CompiledModule.COMPILED_MODULES_ENABLED) {
                AbstractShell.getServerShell(request.nature, AbstractShell.COMPLETION_SHELL); //just start it
            }
            if (DebugSettings.DEBUG_CODE_COMPLETION) {
                Log.toLogFile(this, "END AbstractShell.getServerShell");
            }
        } catch (RuntimeException e) {
            throw e;
        }
    }

    /**
     * @return completions added from contributors
     * @throws MisconfigurationException
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private Collection<Object> getGlobalsFromParticipants(CompletionRequest request, ICompletionState state)
            throws MisconfigurationException {
        ArrayList ret = new ArrayList();

        List participants = ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_COMPLETION);
        for (Iterator iter = participants.iterator(); iter.hasNext();) {
            IPyDevCompletionParticipant participant = (IPyDevCompletionParticipant) iter.next();
            ret.addAll(participant.getGlobalCompletions(request, state));
        }
        return ret;
    }

    /**
     * @param request this is the request for the completion
     * @param theList OUT - returned completions are added here. (IToken instances)
     * @param getOnlySupers whether we should only get things from super classes (in this case, we won't get things from the current class)
     * @param checkIfInCorrectScope if true, we'll first check if we're in a scope that actually has a method with 'self' or 'cls'
     *
     * @return true if we actually tried to get the completions for self or cls.
     * @throws MisconfigurationException
     */
    @SuppressWarnings("unchecked")
    public static boolean getSelfOrClsCompletions(CompletionRequest request, List theList, ICompletionState state,
            boolean getOnlySupers, boolean checkIfInCorrectScope, String lookForRep) throws MisconfigurationException {

        IModule module = request.getModule();
        SimpleNode s = null;
        if (module instanceof SourceModule) {
            SourceModule sourceModule = (SourceModule) module;
            s = sourceModule.getAst();
        }
        if (s != null) {
            FindScopeVisitor visitor = new FindScopeVisitor(state.getLine(), 0);
            try {
                s.accept(visitor);
                if (checkIfInCorrectScope) {
                    boolean scopeCorrect = false;

                    FastStack<SimpleNode> scopeStack = visitor.scope.getScopeStack();
                    for (Iterator<SimpleNode> it = scopeStack.topDownIterator(); scopeCorrect == false && it.hasNext();) {
                        SimpleNode node = it.next();
                        if (node instanceof FunctionDef) {
                            FunctionDef funcDef = (FunctionDef) node;
                            if (funcDef.args != null && funcDef.args.args != null && funcDef.args.args.length > 0) {
                                //ok, we have some arg, let's check for self or cls
                                String rep = NodeUtils.getRepresentationString(funcDef.args.args[0]);
                                if (rep != null && (rep.equals("self") || rep.equals("cls"))) {
                                    scopeCorrect = true;
                                }
                            }
                        }
                    }
                    if (!scopeCorrect) {
                        return false;
                    }
                }
                if (lookForRep.equals("self")) {
                    state.setLookingFor(ICompletionState.LOOKING_FOR_INSTANCED_VARIABLE);
                } else {
                    state.setLookingFor(ICompletionState.LOOKING_FOR_CLASSMETHOD_VARIABLE);
                }
                getSelfOrClsCompletions(visitor.scope, request, theList, state, getOnlySupers);
            } catch (Exception e1) {
                Log.log(e1);
            }
            return true;
        }
        return false;
    }

    /**
     * Get self completions when you already have a scope
     * @throws MisconfigurationException
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void getSelfOrClsCompletions(ILocalScope scope, CompletionRequest request, List theList,
            ICompletionState state, boolean getOnlySupers) throws BadLocationException, MisconfigurationException {
        for (Iterator<SimpleNode> it = scope.iterator(); it.hasNext();) {
            SimpleNode node = it.next();
            if (node instanceof ClassDef) {
                ClassDef d = (ClassDef) node;

                if (getOnlySupers) {
                    for (int i = 0; i < d.bases.length; i++) {
                        if (d.bases[i] instanceof Name) {
                            Name n = (Name) d.bases[i];
                            state.setActivationToken(n.id);
                            IToken[] completions;
                            try {
                                ICodeCompletionASTManager astManager = request.nature.getAstManager();
                                IModule module = request.getModule();
                                if (module != null) {
                                    completions = astManager.getCompletionsForModule(module, state, true, true);
                                    for (int j = 0; j < completions.length; j++) {
                                        theList.add(completions[j]);
                                    }
                                }
                            } catch (CompletionRecursionException e) {
                                //ok...
                            }
                        }
                    }
                } else {
                    //ok, get the completions for the class, only thing we have to take care now is that we may
                    //not have only 'self' for completion, but something like self.foo.
                    //so, let's analyze our activation token to see what should we do.

                    String trimmed = request.activationToken.replace('.', ' ').trim();
                    String[] actTokStrs = trimmed.split(" ");
                    if (actTokStrs.length == 0 || (!actTokStrs[0].equals("self") && !actTokStrs[0].equals("cls"))) {
                        throw new AssertionError(
                                "We need to have at least one token (self or cls) for doing completions in the class.");
                    }

                    if (actTokStrs.length == 1) {
                        //ok, it's just really self, let's get on to get the completions
                        state.setActivationToken(NodeUtils.getNameFromNameTok((NameTok) d.name));
                        try {
                            ICodeCompletionASTManager astManager = request.nature.getAstManager();
                            IModule module = request.getModule();
                            IToken[] completions = astManager.getCompletionsForModule(module, state, true, true);
                            for (int j = 0; j < completions.length; j++) {
                                theList.add(completions[j]);
                            }
                        } catch (CompletionRecursionException e) {
                            //ok
                        }

                    } else {
                        //it's not only self, so, first we have to get the definition of the token
                        //the first one is self, so, just discard it, and go on, token by token to know what is the last
                        //one we are completing (e.g.: self.foo.bar)
                        int line = request.doc.getLineOfOffset(request.documentOffset);
                        IRegion region = request.doc.getLineInformationOfOffset(request.documentOffset);
                        int col = request.documentOffset - region.getOffset();

                        //ok, try our best shot at getting the module name of the current buffer used in the request.
                        IModule module = request.getModule();

                        AbstractASTManager astMan = ((AbstractASTManager) request.nature.getAstManager());
                        theList.addAll(new AssignAnalysis().getAssignCompletions(astMan, module, new CompletionState(
                                line, col, request.activationToken, request.nature, request.qualifier)).completions);
                    }
                }
            }
        }
    }

}
TOP

Related Classes of org.python.pydev.editor.codecompletion.PyCodeCompletion

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.